﻿using System;
using System.Net;
using System.Net.Mime;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace WebServer
{
	/// <summary>
	/// Provides an interface structure for WebObjects
	/// </summary>
	public interface IWebObject
	{
		/// <summary>
		/// Gets the UID for this WebObject.
		/// </summary>
		UID UID { get; }

		/// <summary>
		/// Gets a value indecating whether this instance of WebObject has been deleted.
		/// </summary>
		bool Deleted { get; }

		/// <summary>
		/// Gets or Sets a value indecating whether this instance of WebObject should output data in 'real time'. 
		/// This will cause all Elements added to this WebObject to be sent directly to the request output stream.
		/// </summary>
		bool RealTime { get; set; }

		/// <summary>
		/// Gets or Sets the physical FileInfo data associated with this WebObject.
		/// </summary>
		FileInfo FileData { get; set; }

		/// <summary>
		/// Gets or Sets a value indecating whether this WebObject is an ASP.NET script.
		/// </summary>
		bool AspScript { get; set; }

		/// <summary>
		/// Gets or Sets a value indecating whether this WebObject is a PHP script.
		/// </summary>
		bool PhpScript { get; set; }

		/// <summary>
		/// Gets the raw byte data value of this WebObject. 
		/// The WebObject must be Compiled before this variable is populated.
		/// </summary>
		byte[] RawData { get; }

		/// <summary>
		/// Gets or Sets the Mime type associated with this WebObject
		/// </summary>
		string ContentType { get; set; }

		/// <summary>
		/// Gets or Sets the Name of this WebObject
		/// </summary>
		string Name { get; set; }

		/// <summary>
		/// Gets or Sets the VirtualName of this WebObject. 
		/// This variable is used for mapping http requests to the correct virtual WebObject.
		/// </summary>
		string VirtualName { get; }

		/// <summary>
		/// Gets the request URL for this WebObject
		/// </summary>
		Uri RequestURL { get; }

		/// <summary>
		/// Gets or Sets the Client Connection requesting this WebObject.
		/// </summary>
		Client Client { get; set; }

		/// <summary>
		/// Gets the initial HttpListenerContext that holds the request and response data related to this instance of WebObject.
		/// </summary>
		HttpListenerContext Context { get; }

		/// <summary>
		/// Gets the list of elements stored in this WebObject
		/// </summary>
		List<IWebObjectElement> Elements { get; }

		/// <summary>
		/// Gets or Sets the compiled Body code for this WebObject
		/// </summary>
		string Body { get; set; }

		/// <summary>
		/// Inserts an element into the element list
		/// </summary>
		/// <param name="element">Element to insert</param>
		void InsertElement(IWebObjectElement element);

		/// <summary>
		/// Adds an 'html' element to this WebObject
		/// </summary>
		/// <param name="html">HTML code</param>
		void AddHTML(string html);

		/// <summary>
		/// Adds an 'html' element to this WebObject with formatted code
		/// </summary>
		/// <param name="format">String format</param>
		/// <param name="args">Format arguments</param>
		void AddHTML(string format, params object[] args);

		/// <summary>
		/// Adds a 'text' element to this WebObject
		/// </summary>
		/// <param name="text">Plain text</param>
		void AddText(string text);

		/// <summary>
		/// Adds a 'text' element to this WebObject with formatting
		/// </summary>
		/// <param name="format">String format</param>
		/// <param name="args">Format arguments</param>
		void AddText(string format, params object[] args);

		/// <summary>
		/// Adds a 'byte' element to this WebObject.
		/// </summary>
		/// <param name="b">Raw byte data to add.</param>
		void AddByte(byte b);

		/// <summary>
		/// Adds a 'byte array' element to this WebObject.
		/// </summary>
		/// <param name="bytes">Raw byte data array to add.</param>
		void AddByte(byte[] bytes);
		
		/// <summary>
		/// Outputs the contents of FileData to the given output stream. 
		/// If FileData is null, the RawData buffer will be sent to the output stream.
		/// </summary>
		/// <param name="output">The stream for output data.</param>
		void StreamData(Stream output);

		/// <summary>
		/// Outputs the contents of FileData to the given output stream. 
		/// If FileData is null, the RawData buffer will be sent to the output stream.
		/// </summary>
		/// <param name="output">The stream for output data.</param>
		/// <param name="maxBufferLength">The maximum buffer length before a FileBuffer is used to output data.</param>
		void StreamData(Stream output, long maxBufferLength);

		/// <summary>
		/// Outputs the contents of the given buffer to the output stream.
		/// </summary>
		/// <param name="output">The stream for output data.</param>
		/// <param name="buffer">The buffer to write to the output stream.</param>
		void StreamData(Stream output, byte[] buffer);

		/// <summary>
		/// Compiles all elements associated with this WebObject into a single Body string before being sent back as a request reply
		/// </summary>
		/// <returns>Body of this WebObject, compiled into a single string</returns>
		string Compile();

		/// <summary>
		/// Fired when this WebObject is compiled
		/// </summary>
		void OnCompile();

		/// <summary>
		/// Fired just before this WebObject is compiled and determines whether the WebObject should be Compiled
		/// </summary>
		/// <returns>Returns 'true' by default, can be overridden in a derived class to determine whether this WebObject should be compiled or not</returns>
		bool OnBeforeCompile();

		/// <summary>
		/// Fired just after this WebObject is successfully compiled
		/// </summary>
		void OnAfterCompile();

		/// <summary>
		/// Fired when this WebObject is sent as a request reply
		/// </summary>
		void OnSend();

		void Delete();
	}
}
